/**
 * @Descrition:
 * @Param:
 * @Param:
 * @Return:
 * @Auditor :ziliang.zhou
 * @Vesion:1.0.0
 */
package com.sunyard.utils.wxv3Util;

import com.sunyard.exception.IllegalOperationException;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Component;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

/**
 * 证书工具类
 *
 * @author ziliang.zhou
 * @version 1.0 2020年9月4日
 */
@Component
public class CertUtil {


    /**
     * @return
     */
    public static PrivateKey getPrivateKey(String apiclientKeyPath) throws IOException {
        String content = new String(Files.readAllBytes(Paths.get(apiclientKeyPath)), StandardCharsets.UTF_8);
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "").replace("-----END PRIVATE KEY-----", "").replaceAll("\\s+", "");
            //String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC4lBJQDt5sISfbSVO7QGTN6PX6G9YKeh4vpvr0vjtv9XCRTBoQi/f8cf40HMt5wXjkBR3sz5JxaGcG0oT8Fs4gVqYeRd/1l89h9xD9he9iKHOqDLfC5aPEhdHFyKqhD83b+vVV6hS+/J/O2ZYi6PV2rz/MBXqVrGCjgB88WUhKQlnHNrQQI6PhiVgtsBLpocGGgMEA/pr6+8FGSxcJ03eQ77CLt4HpgvpeZPz7X0Jx5o8K4McYjR0MjCa0EPd1mpXVspBaILnsr4Fn7Q9JQonobMdd95PR905aLGQF/htwRIel/VkDaaM6dNNyHhB6896iRAQpc9TX2DxhyakO4hm/AgMBAAECggEAf56ZntL5BKhUB3GGvESErj4xvLF8Z5gRwP7iK1BQhlOcdkm5B9HPL7OdgGicY13a+UV0cGUAqvr1qSjrm+UktgVTLEFB3WwOjnymObReVG8FsgDDGbVvaxTferIJD/1+Z2f4M2P63iaLVBjrjs2l0l7PbIApRs19r+6JKk/NBNH24WA8nQb0Sr/Ta4Uy5zc7MTz9w9haQ3UwX+vcaspakID6eqrkestFGihNAoeyp4J57hc3gelUZ+k3C5rlU/hlEhV9rcWeDSdSbGProPsvlrmNocacjRWvVQHLEJuz+LOdxGU/Vek5EI9FEQKciI43gSjd5CI/KiJ7W6b77d5geQKBgQD0MF6gA8d+nQAqZGaYsBSNF/mhbyFPczq7J/FrNiYK67d7/0I8TqZbpvo12CjRukCbsrkCU6ZdlhSLRozxmz2fN1kMhx3Duzff97+geC7oPk/K9y6Uk/jnSK9yHf+qLKpljcJQmfVxkVve+U5Td5MlWwncw114IrURkY3GiFvNGwKBgQDBgZV/d9iMPSazKO/Q5gWHDHplD4n5ZzoLdmL1DCy2nzjmd7dh8e9K38UV7vG8DEF8rVbNwzf8vKSYWBkzY7NeNO+3YvkKwN5qgkKHQeT6xqpb/aIwKeh61oXGXM/V7o+jpTjE1hTC3hsQeyQT+feOZUw/z4fTriDTVZil3GnkLQKBgGrBqtzySgmEwknGU0R11sZIsQ5u83U0v3yLXfStW7xyiWlgk6iiCgEP41wfANmQQCbR4CiwQY+wyZKKaZxHbo1pOTlM6Splc2wreE/Du141v9TQdEDo4GzdTjbp/ph7ppN3gniSlsfr8OpuvFupb19picpGb1rSca8Yn48olln5AoGBALbkOV5u8ZcqvQccq/1vSs4ntw8JrsixDiWDUWh2h1RcDTWW9RZ3ykmkUey3GHc5xjOGycJUvvf7fD4ZFkiB9SgXNHLJ8sR9IjrcvvCEEV4Mozuq775B/d8MHwgq9K0oe06afJteE+VSc5YSLTlMSvSlPXoaNjCWJaRZBJvPRa5JAoGAIoFWCn8Ne5YkSS/dUjj9E2aBedlIQ/SWEtgOjQKW5bztDwMJkLXZYoH6a6VkAt8eHE06ZuTfTvQB+bzAC9cwyozbNxUTSZ17VBLbKwLQmaOooYihBh3cQUcdW2TElsGixeVdTdUlRlRYLndY62BmiCGLROW+ung7sTAm79xIkSA=";
            System.out.println("private:" + privateKey);
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

    /**
     * 获取商户证书
     *
     * @param apiclientCertPath
     * @return X509证书
     */
    public static X509Certificate getCertificate(String apiclientCertPath) throws IOException {
        InputStream fis = new FileInputStream(apiclientCertPath);
        try (BufferedInputStream bis = new BufferedInputStream(fis)) {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(bis);
            cert.checkValidity();
            return cert;
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书文件", e);
        }
    }

    /**
     * 获取商户证书序列号
     *
     * @param certPath 获取商户证书序列号 传递商号证书路径 apiclient_cert
     * @return
     * @throws IOException
     */
    public static String getSerialNo(String certPath) throws IOException {
        X509Certificate certificate = getCertificate(certPath);
        return certificate.getSerialNumber().toString(16).toUpperCase();
    }

    /**
     * 获取微信平台证书序列号
     *
     * @return
     * @throws Exception
     */
    public static String getCertSerialNo(String applientCert, String apiclientKeyPath, String merchantId) throws Exception {
        try {
            WxHttpResponse response = HttpUrlUtil.sendGet(applientCert, apiclientKeyPath, merchantId);
            if (200 == response.getStatus()) {
                System.out.println(response.getBody());
                JSONObject json = JSONObject.fromObject(response.getBody());
                JSONArray jsonArray = JSONArray.fromObject(json.optString("data"));
                JSONObject jsonObject = jsonArray.getJSONObject(0);
                return jsonObject.optString("serial_no");
            } else {
                throw new IllegalOperationException(JSONObject.fromObject(response.getBody()).getString("message"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取微信平台证书
     *
     * @return
     * @throws Exception
     */
    public static String getCertStr(String url, String body, String applientCert, String apiclientKeyPath, String merchantId, String apiV3) throws Exception {
        try {
            //WxHttpResponse response = HttpUrlUtil.sendGet(url, body, applientCert, apiclientKeyPath, merchantId);
            WxHttpResponse response = null;
            if (200 == response.getStatus()) {
                JSONObject json = JSONObject.fromObject(response.getBody());
                JSONArray jsonArray = JSONArray.fromObject(json.optString("data"));
                JSONObject jsonObject = jsonArray.getJSONObject(0);
                JSONObject jsonCert = JSONObject.fromObject(jsonObject.optString("encrypt_certificate"));
                String certKeyString = AesUtil.decryptToString(jsonCert.getString("associated_data").getBytes(),
                        jsonCert.getString("nonce").getBytes(), jsonCert.getString("ciphertext"), apiV3);
                return certKeyString;
            } else {
                throw new IllegalOperationException(JSONObject.fromObject(response.getBody()).getString("message"));
            }

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        try {
            System.out.println(getSerialNo("D:/cet/1900009211证书及API秘钥/1900009211_20191209_cert/apiclient_cert.pem"));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}